package com.comp6231.client;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.concurrent.CyclicBarrier;

import org.omg.CORBA.ORB;

import DPIS.StationServer;
import DPIS.StationServerHelper;

import com.comp6231.common.Log;
import com.comp6231.replica1.exception.LogOperationException;

/**
 * 
 * This is the DPIS client system's main class This class verify police offices
 * badge numbers and then connect to servers and provide options to perform
 * operations allowed by server
 * 
 * @author sknarula (narula.sk@gmail.com)
 * @since September 2013
 * 
 * 
 */
public class OfficerClientMultithreadTest extends Thread {

	/**
	 * Class attributes to hold the badge number of the office using the system
	 * currently and the server reference
	 */
	String badgeId = null;
	String stationName = null;
	static Scanner keyboard = new Scanner(System.in);

	/**
	 * Declare the server
	 */
	StationServer server = null;
	// save the reference to avoid unnecessary I/O
	String feIOR = null;

	public static CyclicBarrier cb;

	/**
	 * Constructor to lookup the server object based on station name provided
	 * 
	 * @param stationName
	 * @throws IOException
	 */
	public OfficerClientMultithreadTest(String[] args, String stationName,
			String badgeId) throws IOException {
		this.stationName = stationName;
		this.badgeId = badgeId;

		ORB orb = ORB.init(args, null);

		// check if the ior is saved (it is saved upon using it once)
		String ior = feIOR;
		if (ior == null) {
			// accessing the server first time, so get it from file
			BufferedReader br = new BufferedReader(new FileReader(
					System.getProperty("user.dir")
							+ "/src/com/comp6231/frontend/" + "FEIor.txt"));
			ior = br.readLine();
			br.close();
			feIOR = ior;
		}

		org.omg.CORBA.Object o = orb.string_to_object(ior);

		server = StationServerHelper.narrow(o);

	}

	/**
	 * Main method to start the client thread
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("\nOfficer Cleints System started...Welcome\n");

		char userInput;
		do {
			displayMenu();
			String stringInput = keyboard.nextLine();
			userInput = stringInput.charAt(0);

			try {
				switch (userInput) {
				case '1': // test featured with one client
					cb = new CyclicBarrier(1);
					OfficerClientMultithreadTest client = new OfficerClientMultithreadTest(
							args, "SPVM", "SPVM1234");
					client.start();

					client.join();
					break;

				case '2': // test concurrency
					cb = new CyclicBarrier(9);

					OfficerClientMultithreadTest client1 = new OfficerClientMultithreadTest(
							args, "SPVM", "SPVM1111");
					OfficerClientMultithreadTest client2 = new OfficerClientMultithreadTest(
							args, "SPVM", "SPVM2222");
					OfficerClientMultithreadTest client3 = new OfficerClientMultithreadTest(
							args, "SPVM", "SPVM3333");
					OfficerClientMultithreadTest client4 = new OfficerClientMultithreadTest(
							args, "SPVM", "SPVM4444");

					OfficerClientMultithreadTest client5 = new OfficerClientMultithreadTest(
							args, "SPL", "SPL5555");
					OfficerClientMultithreadTest client6 = new OfficerClientMultithreadTest(
							args, "SPL", "SPL6666");
					OfficerClientMultithreadTest client7 = new OfficerClientMultithreadTest(
							args, "SPL", "SPL7777");

					OfficerClientMultithreadTest client8 = new OfficerClientMultithreadTest(
							args, "SPB", "SPB8888");
					OfficerClientMultithreadTest client9 = new OfficerClientMultithreadTest(
							args, "SPB", "SPB9999");

					client1.start();
					client5.start();
					client8.start();
					client2.start();
					client6.start();
					client9.start();
					client3.start();
					client7.start();
					client4.start();

					client1.join();
					client2.join();
					client3.join();
					client4.join();
					client5.join();
					client6.join();
					client7.join();
					client8.join();
					client9.join();

					break;

				}
			} catch (IOException e) {
				System.out
						.println("Officer Client could not connect to the server.");
				e.printStackTrace();
			} catch (InterruptedException e) {
				System.out
						.println("Officer Client threads Interrupted Exception.");
				e.printStackTrace();
			}
		} while (userInput != 'q' && userInput != 'Q');
	}

	/**
	 * Start the thread, and perform tasks based on user input
	 */
	public void run() {
		Log log = null;
		boolean success;

		try {
			cb.await();
		} catch (Exception e) {

		}

		try {
			// System.out.println("Sending Create C Record 0");
			// Create Record # 1 - Criminal
			success = server.createCRecord(badgeId, "John", "Cross", "Theft",
					"CAPTURED");
			// log the creation of the record
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Creation of Criminal Record", badgeId,
					(success ? "Operation Successful"
							: "Operation Failed: See server log for details"));
			log.save();

			// System.out.println("Sending Create C Record 1");
			// Create Record # 2 - Criminal
			success = server.createCRecord(badgeId, "Tim", "Miller", "Robbery",
					"OTR");
			// log the creation of the record
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Creation of Criminal Record", badgeId,
					(success ? "Operation Successful"
							: "Operation Failed: See server log for details"));
			log.save();

			// System.out.println("Sending Create M Record 2");
			// Create Record # 3 - Missing
			success = server.createMRecord(badgeId, "Michael", "James",
					"123 abc street, montreal, qc", "2001-05-06", "Montreal",
					"MISSING");
			// log the creation of the record
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Creation of Missing Record", badgeId,
					(success ? "Operation Successful"
							: "Operation Failed: See server log for details"));
			log.save();

			// // Create Record # 4 - Criminal
			// success = server.createCRecord(badgeId, "David", "Blake",
			// "Kidnap",
			// "OTR");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Creation of Criminal Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Create Record # 5 - Missing
			// success = server.createMRecord(badgeId, "Steve", "Larry",
			// "123 abc street, montreal, qc", "2001-05-06", "Montreal",
			// "FOUND");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Creation of Missing Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Create Record # 6 - Missing - should fail due to wrong status
			// // type
			// success = server.createMRecord(badgeId, "Simon", "Cadieux",
			// "123 abc street, montreal, qc", "2013-05-06", "Montreal",
			// "OTR");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Creation of Missing Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Create Record # 7 - Criminal - should fail due to wrong status
			// // type
			// success = server.createCRecord(badgeId, "Patrick", "Garg",
			// "Kidnap", "FOUND");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Creation of Criminal Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();

			// System.out.println("Sending edit record 3");
			// Edit Criminal Record - should work
			success = server.editRecord(badgeId, "Miller", "CR10001", "OTR");
			// log the creation of the record
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Editing of Criminal Record", badgeId,
					(success ? "Operation Successful"
							: "Operation Failed: See server log for details"));
			log.save();

			// // Edit Criminal Record - should fail as the record Blake will be
			// in
			// // system with record id CR10003
			// success = server
			// .editRecord(badgeId, "Blake", "CR10004", "CAPTURED");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Criminal Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Edit Criminal Record - should fail due to wrong status type
			// success = server.editRecord(badgeId, "Cross", "CR10000",
			// "MISSING");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Criminal Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Edit Missing Record - should work
			// success = server.editRecord(badgeId, "James", "MR10002",
			// "FOUND");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Missing Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Edit Missing Record - should fail as the record Blake will be
			// in
			// // system with record id CR10004
			// success = server.editRecord(badgeId, "Blake", "MR10004",
			// "FOUND");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Missing Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();
			//
			// // Edit Missing Record - should fail due to wrong status
			// success = server
			// .editRecord(badgeId, "Larry", "MR10004", "CAPTURED");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Missing Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();

			// System.out.println("Sending get count 4");
			// Check Record Count
			String countReturned = server.getRecordCounts(badgeId);
			System.out.println(countReturned);
			// log the count request
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Record Count", badgeId,
					"message=Count Returned: \"" + countReturned + "\"");
			log.save();

			// System.out.println("Sending transfer record 5");
			// Transfer Record
			String transferTo = "";
			if (this.stationName.equals("SPVM"))
				transferTo = "SPL";
			if (this.stationName.equals("SPL"))
				transferTo = "SPB";
			if (this.stationName.equals("SPB"))
				transferTo = "SPVM";
			success = server.transferRecord(badgeId, "CR10000", transferTo);
			// log the creation of the record
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Transfer of Criminal Record CR10000", badgeId,
					(success ? "Operation Successful"
							: "Operation Failed: See server log for details"));
			log.save();

			// System.out.println("Sending get count 6");
			// Check Record Count
			countReturned = server.getRecordCounts(badgeId);
			System.out.println(countReturned);
			// log the count request
			log = new Log(System.getProperty("user.dir")
					+ "/src/com/comp6231/client/logs/" + badgeId + ".txt",
					"Requested Record Count", badgeId,
					"message=Count Returned: \"" + countReturned + "\"");
			log.save();

			// // try to edit the transfered record - should fail as the record
			// is
			// // transferred to SPL station
			// success = server.editRecord(badgeId, "Cross", "CR10000", "OTR");
			// // log the creation of the record
			// log = new Log(System.getProperty("user.dir") +
			// "/src/com/comp6231/client/logs/" + badgeId + ".txt",
			// "Requested Editing of Criminal Record", badgeId,
			// (success ? "Operation Successful"
			// : "Operation Failed: See server log for details"));
			// log.save();

		} catch (LogOperationException e) {
			System.out.println(e.getMessage());
			System.out.println("\n");
		}

	}

	/**
	 * Method to display the menu
	 */
	private static void displayMenu() {
		System.out.println("\nOptions: ");
		System.out
				.println("1:	Test: Create/Edit Criminal/Missing Record, Get Count and transfer records");
		System.out.println("2:	Test: Concurrency");
		System.out.println("q:	Quit");

		System.out.println("\nPlease enter your choice.");
	}
}
